using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace DE.Sdc.SharePoint.Common.Deployment
{
    [Serializable]
    [XmlType(AnonymousType = true, Namespace = "http://sdc/2009/07/Deployment/1.0/ContentStructure")]
    [XmlRoot(Namespace = "http://sdc/2009/07/Deployment/1.0/ContentStructure", IsNullable = false)]
    public class Permissions
    {
        [XmlAttribute]
        public RoleInheritanceType RoleInheritance { get; set; }

        [XmlAttribute]
        public bool ResetRoleInheritance { get; set; }

        [XmlElement("Permission")]
        public List<Permission> Items { get; set; }


        /// <summary>
        /// Sets the permissions for an object
        /// </summary>
        /// <param name="itemDefinition">Xml object for an IBaseItem</param>
        /// <param name="sharePointObject">The ISecurableObject that properties should changed</param>
        /// <param name="parentWeb">The parentWeb or web (if sharePointObject is a web) of the sharePointObject</param>
        protected internal static void SetPermissions(IBaseItem itemDefinition, ISecurableObject sharePointObject, SPWeb parentWeb)
        {
            Trace.WriteLine("Try to set permissions on '" + itemDefinition.Title + "' with url '" + itemDefinition.Url + "'.", "ContentStructureImporter:SetPermissions");

            if (sharePointObject == null || itemDefinition.Permissions == null)
                return;

            if (itemDefinition.Permissions.RoleInheritance == RoleInheritanceType.Break || itemDefinition.Permissions.RoleInheritance == RoleInheritanceType.BreakCopyFromParent)
            {
                if (itemDefinition.Permissions.ResetRoleInheritance)
                    sharePointObject.ResetRoleInheritance();

                sharePointObject.BreakRoleInheritance(itemDefinition.Permissions.RoleInheritance == RoleInheritanceType.BreakCopyFromParent);
            }
            else if (itemDefinition.Permissions.RoleInheritance == RoleInheritanceType.Reset)
                sharePointObject.ResetRoleInheritance();

            for (int i = 0; i < itemDefinition.Permissions.Items.Count; i++)
            {
                Permission permission = itemDefinition.Permissions.Items[i];
                string[] roles = permission.Roles.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);

                SPRoleAssignment roleAssignment = new SPRoleAssignment(permission.User, null, null, null);

                for (int j = 0; j < roles.Length; j++)
                {
                    SPRoleDefinition roleDefinition = GetRoleDefinition(parentWeb, roles[j], parentWeb.HasUniqueRoleDefinitions);
                    if (roleDefinition != null && !roleAssignment.RoleDefinitionBindings.Contains(roleDefinition))
                    {
                        roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
                        sharePointObject.RoleAssignments.Add(roleAssignment);
                    }
                }
            }

            Trace.WriteLine("Permissions on '" + itemDefinition.Title + "' with url '" + itemDefinition.Url + "' set.", "ContentStructureImporter:SetPermissions");
        }

        private static SPRoleDefinition GetRoleDefinition(SPWeb parentWeb, string role, bool hasUniqueRoleDefinitions)
        {
            for (int i = 0; i < parentWeb.RoleDefinitions.Count; i++)
            {
                if (parentWeb.RoleDefinitions[i].Name == role)
                    return parentWeb.RoleDefinitions[i];
            }

            if (parentWeb.ParentWeb != null && !hasUniqueRoleDefinitions)
                GetRoleDefinition(parentWeb.ParentWeb, role, parentWeb.ParentWeb.HasUniqueRoleDefinitions);

            return null;
        }
    }
}